Assignment 1: Visualization of mosquito’s populations

1.1

For the year 2004 the plots demonstrate the preattentive perception problem. At first glance we observe that there were no incidence of the Aedes albopictus species in Africa while higher occurrence of the same is observed in North America (USA more than Mexico), Southern Europe (Spain, Italy and Croatia), and East Asia (Taiwan Japan). Regarding Taiwan, at first one would interpret the map as there being no occurrences of Aedes aegypti, but on further zooming one notices there was such observations. The occurrences of Aedes albopictus in Europe cannot be stated as high density because there were only two observation areas in Spain and one in each Italy and Croatia. In the USA the Aedes albopictus species has higher density in Mississippi state. Aedes aegypti has higher density in West Coast of Brazil and along the coast of Venezuela.


aegypti %>%
  select(VECTOR, Y, X, YEAR, COUNTRY) %>% # selecting variables
  filter(YEAR == 2004) %>% # filter by year
  plot_mapbox(x = ~X, y =~Y, split = ~VECTOR, mode = "scattermapbox", hoverinfo = "name" ) %>% # scattemapbox
  layout( title = "Scatter plot of mosquitos 2004",
        mapbox = list(style = "light"),
        margin = list(r = 25, l = 25, b = 25, t = 25, pad = 0),
        legend = list(orientation = "h", font = list(size = 8))
        )

Between the plots of 2004 and 2013, there’s a clear distinction. Brazil and East of South America in general appeared to have an infestation of the Aedes aegypti, while Taiwan had an increase in spread of the Aedes albopictus towards the northern coast. North America seemed to have gotten rid of the Aedes albopictus. We hypothesize that researchers were more keen on Brazil because of the Zika virus epidemic, therefore it does not necessarily mean that other areas were able to eradicate the mosquito.

# 2013 scatter plot of mosquitos
aegypti %>%
  select(VECTOR, Y, X, YEAR, COUNTRY) %>%
  filter(YEAR == 2013) %>%
  plot_mapbox(x = ~X, y =~Y, split = ~VECTOR, mode = "scattermapbox", hoverinfo = "name" ) %>%
  layout( title = "Scatter plot of mosquitos 2004",
        mapbox = list(style = "light"),
        margin = list(r = 25, l = 25, b = 25, t = 25, pad = 0.5),
        legend = list(orientation = "h", font = list(size = 8))
        )

1.2

There is little information on the map because of the continuous scale on the big range between the observations. For example, India has Z value of 583 while Canada has Z value of 1 yet they have the same color shading.

# compute z (no. of mosquitos detected per country); choropleth
aegypti %>%
  group_by(COUNTRY) %>%
  mutate(Z = n()) %>%
  plot_geo() %>%
  add_trace(
    z =~Z, name = 'Mosquito (Z)', color =~Z, color = "reds",
    locations =~COUNTRY_ID
  ) %>%
  layout(
    title = "Number of mosquitos detected per country",
    geo = list(
  projection = list(type = "equirectangular")
    )
  )

1.3

With the Z value scaled we get a clear comparison of the number of mosquito detected in each country. Brazil has the highest number followed by USA. East Africa, most of the countries in West Africa, China, India, are in-between the ranges of 6 and 4.


aegypti %>%
  group_by(COUNTRY) %>%
  mutate(Z = log(n())) %>%
  plot_geo() %>%
  add_trace(
    z =~Z, name = 'Mosquito (Z)', color =~Z, color = "reds",
    locations =~COUNTRY_ID
  ) %>%
  layout(
    title = "Number of mosquitos detected per country (graph a)",
    geo = list(
  projection = list(type = "equirectangular")
    )
  )

Comparing graph a and b; while graph b is fancier and nice to look at it is not easy to judge compared to graph a. The disadvantage of graph a is that further north or south of equator continents appear larger than they actually are (Delaney 2015). For the conic in graph b shapes and distances are not correct.

aegypti %>%
  group_by(COUNTRY) %>%
  mutate(Z = log(n())) %>%
  plot_geo() %>%
  add_trace(
    z =~Z, name = 'Mosquito (Z)', color =~Z, color = "reds",
    locations =~COUNTRY_ID
  ) %>%
  layout(
    title = "Number of mosquitos detected per country (graph b)",
    geo = list(projection = list(type = "conic equal area"))
  )

1.4

The discretization carried out helps in getting accurate information from the map. Areas that had high distribution of mosquito in Brazil were in the states of Paraiba (16 and 15), Rio Grande Do Norte (12 and 14), Sau Paulo (13).

aegypti %>%
 select(VECTOR, Y, X, YEAR, COUNTRY) %>%
 filter(YEAR == 2013., COUNTRY == "Brazil") %>%
 mutate(X1 = cut_interval(X, 100)) %>%
 mutate(Y1 = cut_interval(Y, 100)) %>% 
 group_by(X1,Y1) %>%
 summarise(mx = mean(X), my =mean(Y), N = n()) %>%
 plot_mapbox( mode = "scattermapbox", hoverinfo = "name") %>%
 add_markers(x = ~mx, y = ~my, split =~N,size = ~N) %>%
 layout( title = "Scatter plot of mosquitos 2013",
        mapbox = list(style = "light"),
        margin = list(r = 25, l = 25, b = 25, t = 25, pad = 0.5),
        legend = list(orientation = "h", font=list(size = 8))
        )

Assignment 2: Visualization of income in Swedish household

2.1 Age groups as Young, Adult and Senior

levels(df$age) <- c("Young", "Adult", "Senior")
df1 <- spread(df, age, X2016)
colnames(df1) <- c("Region","Young","Adult","Senior")

2.2 Violin plot showing mean income distributions per age group

Mean values: Young = 310.20 ; Adult = 502.02 ; Senior = 524.09 The wider part of the violin plot shows higher probability. This indicates that the mean income of young,adult, and senior is highly concentrated around the median. The mean income of young is lower than both adult and senior incomes.

p <- ggplot(df, aes(age,X2016,fill=age))+labs(title="Plot of mean income distributions by age",x="Age", y = "Mean income distributions")+ geom_violin(trim = FALSE)+stat_summary(fun.y=median, geom="point", shape=23, size=2, color="#1c1c19")+scale_fill_brewer(palette="Dark2")
ggplotly(p)

2.3 Surface plot showing dependence of Senior incomes on Adult and Young incomes in various counties.

The trend is monotonically increasing and this also suggests an additive model. A linear regression model is an additive model hence it can be used to model the data. Furthermore, the dependent variable Senior incomes is continuous.

#df1 %>%plot_ly(x=~Young, y=~Adult, z=~Senior, type="scatter3d")
library(akima)
attach(df1)
s=interp(Adult,Senior,Young)
detach(df1)
df1 %>%
  plot_ly(x=~s$x, y=~s$y, z=~s$z, name='') %>% layout(title = "Surface plot",
    scene = list(
      xaxis = list(title = "Adult"),
      yaxis = list(title = "Senior"),
      zaxis = list(title = "Young")
    )) %>% add_surface()

2.4 Choropleth maps for Young and Adult

From the maps, we can associate mean incomes to regions Sweden. Mean income of the young is high in Stockholm. Halland has the second highest mean income while Värmland and Västerbotten have lowest mean income. Considering mean incomes of the adult, again Stockholm has the highest value. But only Värmland has the lowest mean income for adults.

rownames(df1)=df1$Region
map$Young=df1[map$NAME_1, "Young"]
map$Young[is.na(map$Young)]=0
Young_plot <- plot_ly() %>% add_sf(data=map, split=~NAME_1, color=~Young, showlegend=F, alpha=1) %>%
              layout(title="Incomes of Young")
Young_plot

map$Adult=df1[map$NAME_1, "Adult"]
map$Adult[is.na(map$Adult)]=0
Adult_plot <- plot_ly() %>% add_sf(data=map, split=~NAME_1, color=~Adult, showlegend=F, alpha=1) %>% layout(title="Incomes of Adult")
              
Adult_plot

2.5 Locate Linköping

long <- 15.624525
lat <- 58.409814

Young_plot %>% add_trace(x = ~long, y = ~lat, mode='markers', color="#8B0000",hoverinfo<-"text", text="Linköping") %>% layout(title="Linköping")

This red dot shows where we are located :)

Appendix

library(ggplot2)
library(plotly)
library(MASS)
library(gridExtra)
library(sp)
library(sf)
library(tidyr)
library(dplyr)
library(RColorBrewer)
library(akima)
# Access key token
Sys.setenv('MAPBOX_TOKEN' = 'pk.eyJ1IjoiYnJpbWEiLCJhIjoiY2ptYm5pbXZ6MDd1czNwcW10OHN4Y2theSJ9.SNmXpvkIL14Wn1ebhRr_ug')
# loading the data
aegypti <- read.csv("aegypti_albopictus.csv", header = TRUE, sep = ",")

aegypti %>%
  select(VECTOR, Y, X, YEAR, COUNTRY) %>% # selecting variables
  filter(YEAR == 2004) %>% # filter by year
  plot_mapbox(x = ~X, y =~Y, split = ~VECTOR, mode = "scattermapbox", hoverinfo = "name" ) %>% # scattemapbox
  layout( title = "Scatter plot of mosquitos 2004",
        mapbox = list(style = "light"),
        margin = list(r = 25, l = 25, b = 25, t = 25, pad = 0),
        legend = list(orientation = "h", font = list(size = 8))
        )
# 2013 scatter plot of mosquitos
aegypti %>%
  select(VECTOR, Y, X, YEAR, COUNTRY) %>%
  filter(YEAR == 2013) %>%
  plot_mapbox(x = ~X, y =~Y, split = ~VECTOR, mode = "scattermapbox", hoverinfo = "name" ) %>%
  layout( title = "Scatter plot of mosquitos 2004",
        mapbox = list(style = "light"),
        margin = list(r = 25, l = 25, b = 25, t = 25, pad = 0.5),
        legend = list(orientation = "h", font = list(size = 8))
        )
# compute z (no. of mosquitos detected per country); choropleth
aegypti %>%
  group_by(COUNTRY) %>%
  mutate(Z = n()) %>%
  plot_geo() %>%
  add_trace(
    z =~Z, name = 'Mosquito (Z)', color =~Z, color = "reds",
    locations =~COUNTRY_ID
  ) %>%
  layout(
    title = "Number of mosquitos detected per country",
    geo = list(
  projection = list(type = "equirectangular")
    )
  )


aegypti %>%
  group_by(COUNTRY) %>%
  mutate(Z = log(n())) %>%
  plot_geo() %>%
  add_trace(
    z =~Z, name = 'Mosquito (Z)', color =~Z, color = "reds",
    locations =~COUNTRY_ID
  ) %>%
  layout(
    title = "Number of mosquitos detected per country (graph a)",
    geo = list(
  projection = list(type = "equirectangular")
    )
  )
aegypti %>%
  group_by(COUNTRY) %>%
  mutate(Z = log(n())) %>%
  plot_geo() %>%
  add_trace(
    z =~Z, name = 'Mosquito (Z)', color =~Z, color = "reds",
    locations =~COUNTRY_ID
  ) %>%
  layout(
    title = "Number of mosquitos detected per country (graph b)",
    geo = list(projection = list(type = "conic equal area"))
  )
aegypti %>%
 select(VECTOR, Y, X, YEAR, COUNTRY) %>%
 filter(YEAR == 2013., COUNTRY == "Brazil") %>%
 mutate(X1 = cut_interval(X, 100)) %>%
 mutate(Y1 = cut_interval(Y, 100)) %>% 
 group_by(X1,Y1) %>%
 summarise(mx = mean(X), my =mean(Y), N = n()) %>%
 plot_mapbox( mode = "scattermapbox", hoverinfo = "name") %>%
 add_markers(x = ~mx, y = ~my, split =~N,size = ~N) %>%
 layout( title = "Scatter plot of mosquitos 2013",
        mapbox = list(style = "light"),
        margin = list(r = 25, l = 25, b = 25, t = 25, pad = 0.5),
        legend = list(orientation = "h", font=list(size = 8))
        )
map<-readRDS("swe_map.rds")
df<-read.csv("mean_income.csv")
#View(df)
levels(df$age) <- c("Young", "Adult", "Senior")
df1 <- spread(df, age, X2016)
colnames(df1) <- c("Region","Young","Adult","Senior")
p <- ggplot(df, aes(age,X2016,fill=age))+labs(title="Plot of mean income distributions by age",x="Age", y = "Mean income distributions")+ geom_violin(trim = FALSE)+stat_summary(fun.y=median, geom="point", shape=23, size=2, color="#1c1c19")+scale_fill_brewer(palette="Dark2")
ggplotly(p)
#df1 %>%plot_ly(x=~Young, y=~Adult, z=~Senior, type="scatter3d")
library(akima)
attach(df1)
s=interp(Adult,Senior,Young)
detach(df1)

df1 %>%
  plot_ly(x=~s$x, y=~s$y, z=~s$z, name='') %>% layout(title = "Surface plot",
    scene = list(
      xaxis = list(title = "Adult"),
      yaxis = list(title = "Senior"),
      zaxis = list(title = "Young")
    )) %>% add_surface()
df1 <- df1 %>% separate(Region,c("Num","Region","County"),extra = 'drop') %>% select('Region','Young','Adult','Senior')

df1[df1$Region=="Örebro",][1]="Orebro"
df1[df1$Region=="Västra",][1]="Västra Götaland"
#View(df1)
rownames(df1)=df1$Region
map$Young=df1[map$NAME_1, "Young"]
map$Young[is.na(map$Young)]=0
Young_plot <- plot_ly() %>% add_sf(data=map, split=~NAME_1, color=~Young, showlegend=F, alpha=1) %>%
              layout(title="Incomes of Young")
Young_plot

map$Adult=df1[map$NAME_1, "Adult"]
map$Adult[is.na(map$Adult)]=0
Adult_plot <- plot_ly() %>% add_sf(data=map, split=~NAME_1, color=~Adult, showlegend=F, alpha=1) %>% layout(title="Incomes of Adult")
              
Adult_plot
long <- 15.624525
lat <- 58.409814

Young_plot %>% add_trace(x = ~long, y = ~lat, mode='markers', color="#8B0000",hoverinfo<-"text", text="Linköping") %>% layout(title="Linköping")

References

Delaney, Ian. 2015. “The Problem with Projections.” Web article. https://360.here.com/2015/05/25/problem-projections/.

LS0tDQp0aXRsZTogIlZpc3VhbGl6YXRpb24gTGFiIDMiDQphdXRob3I6ICJSb3NobmkgU3VuZGFyYW11cnRoeSAocm9zc3U4MDkpICYgQnJpYW4gTWFzaW5kZSAoYnJpbWE3NDgpIg0KZGF0ZTogIjI2IFNlcHRlbWJlciAyMDE4Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGRmX3ByaW50OiBwYWdlZA0KICBodG1sX25vdGVib29rOg0KICAgIHRoZW1lOiBqb3VybmFsDQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KZm9udHNpemU6IDExcHQNCmJpYmxpb2dyYXBoeTogcmVmZXJlbmNlcy5iaWINCi0tLQ0KDQoNCmBgYHtyIGxpYnJhcmllcywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkoZ3JpZEV4dHJhKQ0KbGlicmFyeShzcCkNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KbGlicmFyeShha2ltYSkNCmBgYA0KDQojIyBBc3NpZ25tZW50IDE6IFZpc3VhbGl6YXRpb24gb2YgbW9zcXVpdG/igJlzIHBvcHVsYXRpb25zDQpgYGB7ciBhY2Nlc3MsIGVjaG89RkFMU0V9DQojIEFjY2VzcyBrZXkgdG9rZW4NClN5cy5zZXRlbnYoJ01BUEJPWF9UT0tFTicgPSAncGsuZXlKMUlqb2lZbkpwYldFaUxDSmhJam9pWTJwdFltNXBiWFo2TURkMWN6TndjVzEwT0hONFkydGhlU0o5LlNObVhwdmtJTDE0V24xZWJoUnJfdWcnKQ0KYGBgDQoNCmBgYHtyIGRhdGEsIGVjaG89RkFMU0V9DQojIGxvYWRpbmcgdGhlIGRhdGENCmFlZ3lwdGkgPC0gcmVhZC5jc3YoImFlZ3lwdGlfYWxib3BpY3R1cy5jc3YiLCBoZWFkZXIgPSBUUlVFLCBzZXAgPSAiLCIpDQpgYGANCg0KIyMjIDEuMQ0KDQpGb3IgdGhlIHllYXIgMjAwNCB0aGUgcGxvdHMgZGVtb25zdHJhdGUgdGhlIHByZWF0dGVudGl2ZSBwZXJjZXB0aW9uIHByb2JsZW0uIEF0IGZpcnN0IGdsYW5jZSB3ZSBvYnNlcnZlIHRoYXQgdGhlcmUgd2VyZSBubyBpbmNpZGVuY2Ugb2YgdGhlICpBZWRlcyBhbGJvcGljdHVzKiBzcGVjaWVzIGluIEFmcmljYSB3aGlsZSBoaWdoZXIgb2NjdXJyZW5jZSBvZiB0aGUgc2FtZSBpcyBvYnNlcnZlZCBpbiBOb3J0aCBBbWVyaWNhIChVU0EgbW9yZSB0aGFuIE1leGljbyksIFNvdXRoZXJuIEV1cm9wZSAoU3BhaW4sIEl0YWx5IGFuZCBDcm9hdGlhKSwgYW5kIEVhc3QgQXNpYSAoVGFpd2FuIEphcGFuKS4gUmVnYXJkaW5nIFRhaXdhbiwgYXQgZmlyc3Qgb25lIHdvdWxkIGludGVycHJldCB0aGUgbWFwIGFzIHRoZXJlIGJlaW5nIG5vICBvY2N1cnJlbmNlcyBvZiAqQWVkZXMgYWVneXB0aSosIGJ1dCBvbiBmdXJ0aGVyIHpvb21pbmcgb25lIG5vdGljZXMgdGhlcmUgd2FzIHN1Y2ggb2JzZXJ2YXRpb25zLiBUaGUgb2NjdXJyZW5jZXMgb2YgKkFlZGVzIGFsYm9waWN0dXMqIGluIEV1cm9wZSBjYW5ub3QgYmUgc3RhdGVkIGFzIGhpZ2ggZGVuc2l0eSBiZWNhdXNlIHRoZXJlIHdlcmUgb25seSB0d28gb2JzZXJ2YXRpb24gYXJlYXMgaW4gU3BhaW4gYW5kIG9uZSBpbiBlYWNoIEl0YWx5IGFuZCBDcm9hdGlhLiAgSW4gdGhlIFVTQSB0aGUgKkFlZGVzIGFsYm9waWN0dXMqIHNwZWNpZXMgaGFzIGhpZ2hlciBkZW5zaXR5IGluIE1pc3Npc3NpcHBpIHN0YXRlLiAqQWVkZXMgYWVneXB0aSogaGFzIGhpZ2hlciBkZW5zaXR5IGluIFdlc3QgQ29hc3Qgb2YgQnJhemlsIGFuZCBhbG9uZyB0aGUgY29hc3Qgb2YgVmVuZXp1ZWxhLg0KDQpgYGB7ciBxdWVzdGlvbjFfMSwgZmlnLndpZHRoPTEwfQ0KDQphZWd5cHRpICU+JQ0KICBzZWxlY3QoVkVDVE9SLCBZLCBYLCBZRUFSLCBDT1VOVFJZKSAlPiUgIyBzZWxlY3RpbmcgdmFyaWFibGVzDQogIGZpbHRlcihZRUFSID09IDIwMDQpICU+JSAjIGZpbHRlciBieSB5ZWFyDQogIHBsb3RfbWFwYm94KHggPSB+WCwgeSA9flksIHNwbGl0ID0gflZFQ1RPUiwgbW9kZSA9ICJzY2F0dGVybWFwYm94IiwgaG92ZXJpbmZvID0gIm5hbWUiICkgJT4lICMgc2NhdHRlbWFwYm94DQogIGxheW91dCggdGl0bGUgPSAiU2NhdHRlciBwbG90IG9mIG1vc3F1aXRvcyAyMDA0IiwNCiAgICAgICAgbWFwYm94ID0gbGlzdChzdHlsZSA9ICJsaWdodCIpLA0KICAgICAgICBtYXJnaW4gPSBsaXN0KHIgPSAyNSwgbCA9IDI1LCBiID0gMjUsIHQgPSAyNSwgcGFkID0gMCksDQogICAgICAgIGxlZ2VuZCA9IGxpc3Qob3JpZW50YXRpb24gPSAiaCIsIGZvbnQgPSBsaXN0KHNpemUgPSA4KSkNCiAgICAgICAgKQ0KYGBgDQoNCkJldHdlZW4gdGhlIHBsb3RzIG9mIDIwMDQgYW5kIDIwMTMsIHRoZXJlJ3MgYSBjbGVhciBkaXN0aW5jdGlvbi4gQnJhemlsIGFuZCBFYXN0IG9mIFNvdXRoIEFtZXJpY2EgaW4gZ2VuZXJhbCBhcHBlYXJlZCB0byBoYXZlIGFuIGluZmVzdGF0aW9uIG9mIHRoZSAqQWVkZXMgYWVneXB0aSosIHdoaWxlIFRhaXdhbiBoYWQgYW4gaW5jcmVhc2UgaW4gc3ByZWFkIG9mIHRoZSAqQWVkZXMgYWxib3BpY3R1cyogdG93YXJkcyB0aGUgbm9ydGhlcm4gY29hc3QuIE5vcnRoIEFtZXJpY2Egc2VlbWVkIHRvIGhhdmUgZ290dGVuIHJpZCBvZiB0aGUgKkFlZGVzIGFsYm9waWN0dXMqLiBXZSBoeXBvdGhlc2l6ZSB0aGF0IHJlc2VhcmNoZXJzIHdlcmUgbW9yZSBrZWVuIG9uIEJyYXppbCBiZWNhdXNlIG9mIHRoZSBaaWthIHZpcnVzIGVwaWRlbWljLCB0aGVyZWZvcmUgaXQgZG9lcyBub3QgbmVjZXNzYXJpbHkgbWVhbiB0aGF0IG90aGVyIGFyZWFzIHdlcmUgYWJsZSB0byBlcmFkaWNhdGUgdGhlIG1vc3F1aXRvLg0KDQpgYGB7ciBxdWVzdGlvbjFfMiwgZmlnLndpZHRoPTEwfQ0KIyAyMDEzIHNjYXR0ZXIgcGxvdCBvZiBtb3NxdWl0b3MNCmFlZ3lwdGkgJT4lDQogIHNlbGVjdChWRUNUT1IsIFksIFgsIFlFQVIsIENPVU5UUlkpICU+JQ0KICBmaWx0ZXIoWUVBUiA9PSAyMDEzKSAlPiUNCiAgcGxvdF9tYXBib3goeCA9IH5YLCB5ID1+WSwgc3BsaXQgPSB+VkVDVE9SLCBtb2RlID0gInNjYXR0ZXJtYXBib3giLCBob3ZlcmluZm8gPSAibmFtZSIgKSAlPiUNCiAgbGF5b3V0KCB0aXRsZSA9ICJTY2F0dGVyIHBsb3Qgb2YgbW9zcXVpdG9zIDIwMDQiLA0KICAgICAgICBtYXBib3ggPSBsaXN0KHN0eWxlID0gImxpZ2h0IiksDQogICAgICAgIG1hcmdpbiA9IGxpc3QociA9IDI1LCBsID0gMjUsIGIgPSAyNSwgdCA9IDI1LCBwYWQgPSAwLjUpLA0KICAgICAgICBsZWdlbmQgPSBsaXN0KG9yaWVudGF0aW9uID0gImgiLCBmb250ID0gbGlzdChzaXplID0gOCkpDQogICAgICAgICkNCmBgYA0KDQojIyMgMS4yDQoNClRoZXJlIGlzIGxpdHRsZSBpbmZvcm1hdGlvbiBvbiB0aGUgbWFwIGJlY2F1c2Ugb2YgdGhlIGNvbnRpbnVvdXMgc2NhbGUgb24gdGhlIGJpZyByYW5nZSBiZXR3ZWVuIHRoZSBvYnNlcnZhdGlvbnMuIEZvciBleGFtcGxlLCBJbmRpYSBoYXMgWiB2YWx1ZSBvZiA1ODMgd2hpbGUgQ2FuYWRhIGhhcyBaIHZhbHVlIG9mIDEgeWV0IHRoZXkgaGF2ZSB0aGUgc2FtZSBjb2xvciBzaGFkaW5nLg0KDQpgYGB7ciBxdWVzdGlvbjIsIGZpZy53aWR0aD0xMH0NCiMgY29tcHV0ZSB6IChuby4gb2YgbW9zcXVpdG9zIGRldGVjdGVkIHBlciBjb3VudHJ5KTsgY2hvcm9wbGV0aA0KYWVneXB0aSAlPiUNCiAgZ3JvdXBfYnkoQ09VTlRSWSkgJT4lDQogIG11dGF0ZShaID0gbigpKSAlPiUNCiAgcGxvdF9nZW8oKSAlPiUNCiAgYWRkX3RyYWNlKA0KICAgIHogPX5aLCBuYW1lID0gJ01vc3F1aXRvIChaKScsIGNvbG9yID1+WiwgY29sb3IgPSAicmVkcyIsDQogICAgbG9jYXRpb25zID1+Q09VTlRSWV9JRA0KICApICU+JQ0KICBsYXlvdXQoDQogICAgdGl0bGUgPSAiTnVtYmVyIG9mIG1vc3F1aXRvcyBkZXRlY3RlZCBwZXIgY291bnRyeSIsDQogICAgZ2VvID0gbGlzdCgNCiAgcHJvamVjdGlvbiA9IGxpc3QodHlwZSA9ICJlcXVpcmVjdGFuZ3VsYXIiKQ0KICAgICkNCiAgKQ0KDQpgYGANCg0KIyMjIDEuMw0KDQpXaXRoIHRoZSBaIHZhbHVlIHNjYWxlZCB3ZSBnZXQgYSBjbGVhciBjb21wYXJpc29uIG9mIHRoZSBudW1iZXIgb2YgbW9zcXVpdG8gZGV0ZWN0ZWQgaW4gZWFjaCBjb3VudHJ5LiBCcmF6aWwgaGFzIHRoZSBoaWdoZXN0IG51bWJlciBmb2xsb3dlZCBieSBVU0EuIEVhc3QgQWZyaWNhLCBtb3N0IG9mIHRoZSBjb3VudHJpZXMgaW4gV2VzdCBBZnJpY2EsIENoaW5hLCBJbmRpYSwgYXJlIGluLWJldHdlZW4gdGhlIHJhbmdlcyBvZiA2IGFuZCA0LiANCg0KYGBge3IgUXVlc3Rpb24zX2EsIGZpZy53aWR0aD0xMH0NCg0KYWVneXB0aSAlPiUNCiAgZ3JvdXBfYnkoQ09VTlRSWSkgJT4lDQogIG11dGF0ZShaID0gbG9nKG4oKSkpICU+JQ0KICBwbG90X2dlbygpICU+JQ0KICBhZGRfdHJhY2UoDQogICAgeiA9flosIG5hbWUgPSAnTW9zcXVpdG8gKFopJywgY29sb3IgPX5aLCBjb2xvciA9ICJyZWRzIiwNCiAgICBsb2NhdGlvbnMgPX5DT1VOVFJZX0lEDQogICkgJT4lDQogIGxheW91dCgNCiAgICB0aXRsZSA9ICJOdW1iZXIgb2YgbW9zcXVpdG9zIGRldGVjdGVkIHBlciBjb3VudHJ5IChncmFwaCBhKSIsDQogICAgZ2VvID0gbGlzdCgNCiAgcHJvamVjdGlvbiA9IGxpc3QodHlwZSA9ICJlcXVpcmVjdGFuZ3VsYXIiKQ0KICAgICkNCiAgKQ0KYGBgDQoNCkNvbXBhcmluZyBncmFwaCBhIGFuZCBiOyB3aGlsZSBncmFwaCBiIGlzIGZhbmNpZXIgYW5kIG5pY2UgdG8gbG9vayBhdCBpdCBpcyBub3QgZWFzeSB0byBqdWRnZSBjb21wYXJlZCB0byBncmFwaCBhLiBUaGUgZGlzYWR2YW50YWdlIG9mIGdyYXBoIGEgaXMgdGhhdCBmdXJ0aGVyIG5vcnRoIG9yIHNvdXRoIG9mIGVxdWF0b3IgY29udGluZW50cyBhcHBlYXIgbGFyZ2VyIHRoYW4gdGhleSBhY3R1YWxseSBhcmUgW0BoZXJlbWFwc10uIEZvciB0aGUgY29uaWMgaW4gZ3JhcGggYiBzaGFwZXMgYW5kIGRpc3RhbmNlcyBhcmUgbm90IGNvcnJlY3QuDQoNCmBgYHtyIHF1ZXN0aW9uM19iLCBmaWcud2lkdGg9MTB9DQphZWd5cHRpICU+JQ0KICBncm91cF9ieShDT1VOVFJZKSAlPiUNCiAgbXV0YXRlKFogPSBsb2cobigpKSkgJT4lDQogIHBsb3RfZ2VvKCkgJT4lDQogIGFkZF90cmFjZSgNCiAgICB6ID1+WiwgbmFtZSA9ICdNb3NxdWl0byAoWiknLCBjb2xvciA9flosIGNvbG9yID0gInJlZHMiLA0KICAgIGxvY2F0aW9ucyA9fkNPVU5UUllfSUQNCiAgKSAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gIk51bWJlciBvZiBtb3NxdWl0b3MgZGV0ZWN0ZWQgcGVyIGNvdW50cnkgKGdyYXBoIGIpIiwNCiAgICBnZW8gPSBsaXN0KHByb2plY3Rpb24gPSBsaXN0KHR5cGUgPSAiY29uaWMgZXF1YWwgYXJlYSIpKQ0KICApDQpgYGANCg0KIyMjIDEuNA0KDQpUaGUgZGlzY3JldGl6YXRpb24gY2FycmllZCBvdXQgaGVscHMgaW4gZ2V0dGluZyBhY2N1cmF0ZSBpbmZvcm1hdGlvbiBmcm9tIHRoZSBtYXAuIEFyZWFzIHRoYXQgaGFkIGhpZ2ggZGlzdHJpYnV0aW9uIG9mIG1vc3F1aXRvIGluIEJyYXppbCB3ZXJlIGluIHRoZSBzdGF0ZXMgb2YgUGFyYWliYSAoMTYgYW5kIDE1KSwgUmlvIEdyYW5kZSBEbyBOb3J0ZSAoMTIgYW5kIDE0KSwgU2F1IFBhdWxvICgxMykuDQoNCg0KYGBge3IgcXVlc3Rpb240LCBmaWcud2lkdGg9MTB9DQphZWd5cHRpICU+JQ0KIHNlbGVjdChWRUNUT1IsIFksIFgsIFlFQVIsIENPVU5UUlkpICU+JQ0KIGZpbHRlcihZRUFSID09IDIwMTMuLCBDT1VOVFJZID09ICJCcmF6aWwiKSAlPiUNCiBtdXRhdGUoWDEgPSBjdXRfaW50ZXJ2YWwoWCwgMTAwKSkgJT4lDQogbXV0YXRlKFkxID0gY3V0X2ludGVydmFsKFksIDEwMCkpICU+JSANCiBncm91cF9ieShYMSxZMSkgJT4lDQogc3VtbWFyaXNlKG14ID0gbWVhbihYKSwgbXkgPW1lYW4oWSksIE4gPSBuKCkpICU+JQ0KIHBsb3RfbWFwYm94KCBtb2RlID0gInNjYXR0ZXJtYXBib3giLCBob3ZlcmluZm8gPSAibmFtZSIpICU+JQ0KIGFkZF9tYXJrZXJzKHggPSB+bXgsIHkgPSB+bXksIHNwbGl0ID1+TixzaXplID0gfk4pICU+JQ0KIGxheW91dCggdGl0bGUgPSAiU2NhdHRlciBwbG90IG9mIG1vc3F1aXRvcyAyMDEzIiwNCiAgICAgICAgbWFwYm94ID0gbGlzdChzdHlsZSA9ICJsaWdodCIpLA0KICAgICAgICBtYXJnaW4gPSBsaXN0KHIgPSAyNSwgbCA9IDI1LCBiID0gMjUsIHQgPSAyNSwgcGFkID0gMC41KSwNCiAgICAgICAgbGVnZW5kID0gbGlzdChvcmllbnRhdGlvbiA9ICJoIiwgZm9udD1saXN0KHNpemUgPSA4KSkNCiAgICAgICAgKQ0KYGBgDQoNCg0KIyMgQXNzaWdubWVudCAyOiBWaXN1YWxpemF0aW9uIG9mIGluY29tZSBpbiBTd2VkaXNoIGhvdXNlaG9sZA0KDQpgYGB7ciByZWFkaW5nIGRhdGEgaW50byBSLCBlY2hvID0gRkFMU0V9DQptYXA8LXJlYWRSRFMoInN3ZV9tYXAucmRzIikNCmRmPC1yZWFkLmNzdigibWVhbl9pbmNvbWUuY3N2IikNCiNWaWV3KGRmKQ0KYGBgDQoNCiMjIyAyLjEgQWdlIGdyb3VwcyBhcyBZb3VuZywgQWR1bHQgYW5kIFNlbmlvcg0KYGBge3IgR3JvdXBzIChZb3VuZyxBZHVsdCxTZW5pb3IpfQ0KbGV2ZWxzKGRmJGFnZSkgPC0gYygiWW91bmciLCAiQWR1bHQiLCAiU2VuaW9yIikNCmRmMSA8LSBzcHJlYWQoZGYsIGFnZSwgWDIwMTYpDQpjb2xuYW1lcyhkZjEpIDwtIGMoIlJlZ2lvbiIsIllvdW5nIiwiQWR1bHQiLCJTZW5pb3IiKQ0KYGBgDQoNCiMjIyAyLjIgVmlvbGluIHBsb3Qgc2hvd2luZyBtZWFuIGluY29tZSBkaXN0cmlidXRpb25zIHBlciBhZ2UgZ3JvdXANCg0KTWVhbiB2YWx1ZXM6DQpZb3VuZyA9IDMxMC4yMCA7IEFkdWx0ID0gNTAyLjAyIDsgU2VuaW9yID0gNTI0LjA5DQpUaGUgd2lkZXIgcGFydCBvZiB0aGUgdmlvbGluIHBsb3Qgc2hvd3MgaGlnaGVyIHByb2JhYmlsaXR5LiBUaGlzIGluZGljYXRlcyB0aGF0IHRoZSBtZWFuIGluY29tZSBvZiB5b3VuZyxhZHVsdCwgYW5kIHNlbmlvciBpcyBoaWdobHkgY29uY2VudHJhdGVkIGFyb3VuZCB0aGUgbWVkaWFuLiBUaGUgbWVhbiBpbmNvbWUgb2YgeW91bmcgaXMgbG93ZXIgdGhhbiBib3RoIGFkdWx0IGFuZCBzZW5pb3IgaW5jb21lcy4NCg0KYGBge3IgVmlvbGluIHBsb3R9DQpwIDwtIGdncGxvdChkZiwgYWVzKGFnZSxYMjAxNixmaWxsPWFnZSkpK2xhYnModGl0bGU9IlBsb3Qgb2YgbWVhbiBpbmNvbWUgZGlzdHJpYnV0aW9ucyBieSBhZ2UiLHg9IkFnZSIsIHkgPSAiTWVhbiBpbmNvbWUgZGlzdHJpYnV0aW9ucyIpKyBnZW9tX3Zpb2xpbih0cmltID0gRkFMU0UpK3N0YXRfc3VtbWFyeShmdW4ueT1tZWRpYW4sIGdlb209InBvaW50Iiwgc2hhcGU9MjMsIHNpemU9MiwgY29sb3I9IiMxYzFjMTkiKStzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpDQpnZ3Bsb3RseShwKQ0KYGBgDQoNCiMjIyAyLjMgU3VyZmFjZSBwbG90IHNob3dpbmcgZGVwZW5kZW5jZSBvZiBTZW5pb3IgaW5jb21lcyBvbiBBZHVsdCBhbmQgWW91bmcgaW5jb21lcyBpbiB2YXJpb3VzIGNvdW50aWVzLg0KDQpUaGUgdHJlbmQgaXMgbW9ub3RvbmljYWxseSBpbmNyZWFzaW5nIGFuZCB0aGlzIGFsc28gc3VnZ2VzdHMgYW4gYWRkaXRpdmUgbW9kZWwuIEEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgaXMgYW4gYWRkaXRpdmUgbW9kZWwgaGVuY2UgaXQgY2FuIGJlIHVzZWQgdG8gbW9kZWwgdGhlIGRhdGEuIEZ1cnRoZXJtb3JlLCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIFNlbmlvciBpbmNvbWVzIGlzIGNvbnRpbnVvdXMuDQoNCmBgYHtyIFN1cmZhY2UgcGxvdH0NCiNkZjEgJT4lcGxvdF9seSh4PX5Zb3VuZywgeT1+QWR1bHQsIHo9flNlbmlvciwgdHlwZT0ic2NhdHRlcjNkIikNCmxpYnJhcnkoYWtpbWEpDQphdHRhY2goZGYxKQ0Kcz1pbnRlcnAoQWR1bHQsU2VuaW9yLFlvdW5nKQ0KZGV0YWNoKGRmMSkNCg0KZGYxICU+JQ0KICBwbG90X2x5KHg9fnMkeCwgeT1+cyR5LCB6PX5zJHosIG5hbWU9JycpICU+JSBsYXlvdXQodGl0bGUgPSAiU3VyZmFjZSBwbG90IiwNCiAgICBzY2VuZSA9IGxpc3QoDQogICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiQWR1bHQiKSwNCiAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJTZW5pb3IiKSwNCiAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICJZb3VuZyIpDQogICAgKSkgJT4lIGFkZF9zdXJmYWNlKCkNCmBgYA0KDQpgYGB7ciBTZXBhcmF0aW9uLCBlY2hvPUZBTFNFfQ0KZGYxIDwtIGRmMSAlPiUgc2VwYXJhdGUoUmVnaW9uLGMoIk51bSIsIlJlZ2lvbiIsIkNvdW50eSIpLGV4dHJhID0gJ2Ryb3AnKSAlPiUgc2VsZWN0KCdSZWdpb24nLCdZb3VuZycsJ0FkdWx0JywnU2VuaW9yJykNCg0KZGYxW2RmMSRSZWdpb249PSLDlnJlYnJvIixdWzFdPSJPcmVicm8iDQpkZjFbZGYxJFJlZ2lvbj09IlbDpHN0cmEiLF1bMV09IlbDpHN0cmEgR8O2dGFsYW5kIg0KI1ZpZXcoZGYxKQ0KYGBgDQoNCiMjIyAyLjQgQ2hvcm9wbGV0aCBtYXBzIGZvciBZb3VuZyBhbmQgQWR1bHQNCg0KRnJvbSB0aGUgbWFwcywgd2UgY2FuIGFzc29jaWF0ZSBtZWFuIGluY29tZXMgdG8gcmVnaW9ucyBTd2VkZW4uIE1lYW4gaW5jb21lIG9mIHRoZSB5b3VuZyBpcyBoaWdoIGluIFN0b2NraG9sbS4gSGFsbGFuZCBoYXMgdGhlIHNlY29uZCBoaWdoZXN0IG1lYW4gaW5jb21lIHdoaWxlIFbDpHJtbGFuZCBhbmQgVsOkc3RlcmJvdHRlbiBoYXZlIGxvd2VzdCBtZWFuIGluY29tZS4gQ29uc2lkZXJpbmcgbWVhbiBpbmNvbWVzIG9mIHRoZSBhZHVsdCwgYWdhaW4gU3RvY2tob2xtIGhhcyB0aGUgaGlnaGVzdCB2YWx1ZS4gQnV0IG9ubHkgVsOkcm1sYW5kIGhhcyB0aGUgbG93ZXN0IG1lYW4gaW5jb21lIGZvciBhZHVsdHMuIA0KDQpgYGB7ciBwbG90bHksIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PUZBTFNFfQ0Kcm93bmFtZXMoZGYxKT1kZjEkUmVnaW9uDQptYXAkWW91bmc9ZGYxW21hcCROQU1FXzEsICJZb3VuZyJdDQptYXAkWW91bmdbaXMubmEobWFwJFlvdW5nKV09MA0KWW91bmdfcGxvdCA8LSBwbG90X2x5KCkgJT4lIGFkZF9zZihkYXRhPW1hcCwgc3BsaXQ9fk5BTUVfMSwgY29sb3I9fllvdW5nLCBzaG93bGVnZW5kPUYsIGFscGhhPTEpICU+JQ0KICAgICAgICAgICAgICBsYXlvdXQodGl0bGU9IkluY29tZXMgb2YgWW91bmciKQ0KWW91bmdfcGxvdA0KDQptYXAkQWR1bHQ9ZGYxW21hcCROQU1FXzEsICJBZHVsdCJdDQptYXAkQWR1bHRbaXMubmEobWFwJEFkdWx0KV09MA0KQWR1bHRfcGxvdCA8LSBwbG90X2x5KCkgJT4lIGFkZF9zZihkYXRhPW1hcCwgc3BsaXQ9fk5BTUVfMSwgY29sb3I9fkFkdWx0LCBzaG93bGVnZW5kPUYsIGFscGhhPTEpICU+JSBsYXlvdXQodGl0bGU9IkluY29tZXMgb2YgQWR1bHQiKQ0KICAgICAgICAgICAgICANCkFkdWx0X3Bsb3QNCmBgYA0KDQojIyMgMi41IExvY2F0ZSBMaW5rw7ZwaW5nDQpgYGB7ciBXaGVyZSB3ZSBhcmUgbG9jYXRlZCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0V9DQpsb25nIDwtIDE1LjYyNDUyNQ0KbGF0IDwtIDU4LjQwOTgxNA0KDQpZb3VuZ19wbG90ICU+JSBhZGRfdHJhY2UoeCA9IH5sb25nLCB5ID0gfmxhdCwgbW9kZT0nbWFya2VycycsIGNvbG9yPSIjOEIwMDAwIixob3ZlcmluZm88LSJ0ZXh0IiwgdGV4dD0iTGlua8O2cGluZyIpICU+JSBsYXlvdXQodGl0bGU9IkxpbmvDtnBpbmciKQ0KYGBgDQoNClRoaXMgcmVkIGRvdCBzaG93cyB3aGVyZSB3ZSBhcmUgbG9jYXRlZCA6KQ0KDQojIyBBcHBlbmRpeA0KDQpgYGB7ciByZWYubGFiZWw9a25pdHI6OmFsbF9sYWJlbHMoKSwgZWNobyA9IFQsIGV2YWwgPSBGfQ0KDQpgYGANCg0KIyMgUmVmZXJlbmNlcw==